home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr25 / rxcalc.zip / REXXCAL2.C < prev    next >
Text File  |  1993-03-01  |  19KB  |  397 lines

  1. /*********************************************************************/
  2. /*                                                                   */
  3. /* REXXCAL2 - A simple PM based pocket calculator                    */
  4. /*                                                                   */
  5. /*********************************************************************/
  6.  
  7. /* Standard C libraries */
  8.  
  9. #include <stdlib.h>
  10. #include <stdio.h>
  11. #include <string.h>
  12. #include <math.h>
  13.  
  14.  /* Include specific parts of the OS/2 and presentation manager      */
  15.  /* definitions                                                      */
  16.  
  17. #define INCL_WIN
  18. #include <os2.h>
  19. #define INCL_RXFUNC
  20. #include <rexxsaa.h>
  21.  
  22. /* Include the constants file created by the Dialog Box Editor.      */
  23. /* This include file defines symbols for all elements of the         */
  24. /* calculator dialog.                                                */
  25.  
  26. #include <rexxcal2.h>
  27.  
  28. /* Declare prototypes for all subroutines.                           */
  29.  
  30. INT main(VOID);                        /* Main PM calculator program */
  31.  
  32.                                        /* Calculator dialog          */
  33. MRESULT EXPENTRY Calculator(HWND, ULONG, MPARAM, MPARAM);
  34. VOID    ProcessArithmetic(LONG);       /* Arithmetic processor       */
  35. VOID    AddDigit(INT);                 /* add digit to display       */
  36. INT     GetDisplay(VOID);              /* get display value          */
  37. VOID    SetDisplay(LONG);              /* set new display            */
  38. VOID    ProcessProgram(PSZ);           /* process a programmed key   */
  39.  
  40. /* Define some constants for the calculator dialog                   */
  41.  
  42. #define DISPLAY_WIDTH    20            /* width of display area      */
  43. #define MAX_DIGITS        8            /* maximum digits in display  */
  44.  
  45. /* Global data used for the dialog                                   */
  46.  
  47.  HAB    hab;                           /* Anchor block handle        */
  48.  HWND   hwndCalc;                      /* Handle for calculator      */
  49.                                        /*   dialog (created using    */
  50.                                        /*   the dialog editor)       */
  51.  
  52. /* Global data used for the calculator                               */
  53.  
  54.  UCHAR  display[DISPLAY_WIDTH];        /* Displayed number string    */
  55.  LONG   accumulator;                   /* current register value     */
  56.  LONG   operand;                       /* converted operand number   */
  57.  INT    oldaction;                     /* pending key action         */
  58.  INT    digits;                        /* number of digits in display*/
  59.  
  60. /*********************************************************************/
  61. /* main() - the main calculator program entry point                  */
  62. /*********************************************************************/
  63.  
  64. INT main()
  65. {
  66.   HMQ   hmq;                           /* Message queue handle       */
  67.   QMSG  qmsg;                          /* Receive PM queue message   */
  68.  
  69.                                        /* startup PM usage           */
  70.   hab = WinInitialize(0);              /* Get the anchor block handle*/                                                                                                                                                                                       
  71.   hmq = WinCreateMsgQueue(hab, 0);     /* Create the message queue   */
  72.                                        /* register our window class  */
  73.   WinRegisterClass(hab, "RexxCalc", Calculator, 0l, 0);
  74.  
  75.   /* Load the calculator dialog.  The dialog definitions are in      */
  76.   /* rexxcalc.rc                                                     */
  77.  
  78.   hwndCalc = WinLoadDlg(HWND_DESKTOP, HWND_DESKTOP,
  79.                         NULL,
  80.                         0,     
  81.                         REXXCALC,      /* Dialog ID                  */
  82.                         NULL);
  83.  
  84.   WinSendMsg(hwndCalc, WM_SETICON,     /* Set program icon           */
  85.       (MPARAM)WinLoadPointer(HWND_DESKTOP, 0, REXXCALC), NULL);
  86.  
  87.                                        /* set the window focus       */
  88.   WinSetFocus(HWND_DESKTOP,
  89.       WinWindowFromID(hwndCalc, FID_CLIENT));
  90.  
  91.   /* Process the standard Presentation Manager message loop until    */
  92.   /* we are told to terminate                                        */
  93.  
  94.                                        /* While more messages        */
  95.   while (WinGetMsg(hab, &qmsg, 0, 0, 0))
  96.      WinDispatchMsg(hab, &qmsg);       /* dispatch application       */
  97.                                        /*   message handler          */
  98.  
  99.  
  100.   /* The close option has been selected so we need to clean up       */
  101.   /* our context.                                                    */
  102.  
  103.   WinDestroyWindow(hwndCalc);          /* Destroy the dialog window  */
  104.   WinDestroyMsgQueue(hmq);             /* Destroy the message queue  */
  105.   WinTerminate(hab);                   /* Terminate PM usage         */
  106.   return (0);                          /* Indicate successful        */
  107.                                        /*   completion               */
  108. }
  109.  
  110. /*********************************************************************/
  111. /*                                                                   */
  112. /* Calculator() - the PM WinProc for handling the calculator dialog. */
  113. /* The dialog itself has been created using the dialog box editor.   */
  114. /* This seperates the actual form of the calculator from the program */
  115. /* source.                                                           */
  116. /*                                                                   */
  117. /*********************************************************************/
  118.  
  119. MRESULT EXPENTRY Calculator(
  120.   HWND    hwnd,                        /* window handle              */
  121.   ULONG   msg,                         /* dispatched message id      */
  122.   MPARAM  mp1,                         /* first message parameter    */
  123.   MPARAM  mp2 )                        /* second message parameter   */
  124. {
  125.   ULONG   action;                      /* Action to process          */
  126.  
  127.    switch (msg) {                      /* switch based on the message*/
  128.                                        /* received                   */
  129.  
  130.       /* The initialization message has been received.  We do some   */
  131.       /* additional fixup of the dialog to make it look a little     */
  132.       /* nicer.                                                      */
  133.  
  134.       case WM_INITDLG:
  135.  
  136.          accumulator = 0;              /* clear the accumulator      */
  137.          oldaction = 0;                /* no pending operations      */
  138.          operand = 0;                  /* no operand                 */
  139.          digits = 0;                   /* no digits in display       */
  140.          SetDisplay(accumulator);      /* set initial display value  */
  141.                                        /* update the calculator      */
  142.                                        /* display                    */
  143.          WinSetWindowText(WinWindowFromID(hwnd, DISPLAY), display);
  144.          return FALSE;                 /* initialization complete    */
  145.  
  146.       /* We are going away, time to post a quit message to the       */
  147.       /* message loop.                                               */
  148.  
  149.       case WM_CLOSE:
  150.                                        /* Standard Close processing  */
  151.          WinPostMsg(hwnd, WM_QUIT, 0L, 0L);
  152.          return FALSE;                 /* Exit now                   */
  153.  
  154.       /* We've received a WM_COMMAND message.  WM_COMMAND messages   */
  155.       /* are generated by "pressing" buttons on the calculator.  The */
  156.       /* additional parameters in the received message identify the  */
  157.       /* button that was pressed                                     */
  158.  
  159.       case WM_COMMAND:
  160.  
  161.          action = SHORT1FROMMP(mp1);   /* Extract message sub-type   */
  162.  
  163.          switch (action) {
  164.  
  165.             /* The following buttons will be processed by the actual */
  166.             /* calculator routine                                    */
  167.  
  168.             case BUTTON_CLEAR:         /* Clear key                  */
  169.  
  170.               accumulator = 0;         /* clear the accumulator      */
  171.               oldaction = 0;           /* and any pending operations */
  172.               SetDisplay(accumulator); /* set the new display value  */
  173.                                        /* update the calculator      */
  174.                                        /* display                    */
  175.               WinSetWindowText(WinWindowFromID(hwnd, DISPLAY),
  176.                   display);
  177.               return FALSE;            /* All done                   */
  178.  
  179.             case BUTTON_0:             /* Numeric keys               */
  180.             case BUTTON_1:
  181.             case BUTTON_2:
  182.             case BUTTON_3:
  183.             case BUTTON_4:
  184.             case BUTTON_5:
  185.             case BUTTON_6:
  186.             case BUTTON_7:
  187.             case BUTTON_8:
  188.             case BUTTON_9:
  189.  
  190.                                        /* Add a digit to display     */
  191.               AddDigit(action - BUTTON_0);
  192.                                        /* update the accumulator     */
  193.                                        /* display                    */
  194.               WinSetWindowText(WinWindowFromID(hwnd, DISPLAY),
  195.                   display);
  196.               return FALSE;            /* All done                   */
  197.  
  198.             /* The arithmetic operation keys all have a deferred     */
  199.             /* execution.  When one of these is pressed, the previous*/
  200.             /* arithmetic operation is processed using the           */
  201.             /* accumulator and the current display.  The new operator*/
  202.             /* is saved for later execution.  If no operator exists, */
  203.             /* then the current display is moved to the accumulator  */
  204.             /* and no arithmetic is done                             */
  205.  
  206.             case BUTTON_MULTIPLY:      /* Multiply key               */
  207.             case BUTTON_DIVIDE:        /* Division key               */
  208.             case BUTTON_PLUS:          /* Addition key               */
  209.             case BUTTON_MINUS:         /* Subtraction key            */
  210.             case BUTTON_ENTER:         /* "Total" key                */
  211.             case BUTTON_PROGRAM1:      /* programmed Rexx function   */
  212.             case BUTTON_PROGRAM2:      /* programmed Rexx function   */
  213.  
  214.                                        /* Process pending operations */
  215.               ProcessArithmetic(action);
  216.               SetDisplay(accumulator); /* set the new display value  */
  217.                                        /* update the calculator      */
  218.                                        /* display                    */
  219.               WinSetWindowText(WinWindowFromID(hwnd, DISPLAY),
  220.                   display);
  221.               return FALSE;            /* All done                   */
  222.  
  223.             default:                   /* Unknown, can't handle this */
  224.                return FALSE;
  225.          }
  226.  
  227.       case WM_ERASEBACKGROUND:         /* disable background erase   */
  228.         return MRFROMLONG(TRUE);       /* don't allow this           */
  229.  
  230.       /* Message not handled by us.  PM gives us first chance at all */
  231.       /* messages.  Those we don't want to process we pass on to the */
  232.       /* default dialog procedure.                                   */
  233.  
  234.       default:
  235.          return WinDefWindowProc(hwnd, msg, mp1, mp2);
  236.  
  237.    }
  238.  
  239.    return FALSE;                       /* Should never reach here    */
  240.  }
  241.  
  242. /*********************************************************************/
  243. /*                                                                   */
  244. /* AddDigit(digit) - add a digit to the calculator display           */
  245. /*                                                                   */
  246. /*********************************************************************/
  247.  
  248. VOID AddDigit(
  249.   INT    digit )                       /* new digit to add           */
  250. {
  251.  
  252.   digit += (INT)'0';                   /* convert to character value */
  253.  
  254.   if (digits < MAX_DIGITS) {           /* if small enough            */
  255.      display[digits++] = (UCHAR)digit; /* add new digit to display   */
  256.      display[digits] = '\0';           /* add new string terminator  */
  257.   }
  258. }
  259.  
  260. /*********************************************************************/
  261. /*                                                                   */
  262. /* GetDisplay() - Convert current display value into a binary long   */
  263. /*                integer in the variable operand                    */
  264. /*                                                                   */
  265. /*********************************************************************/
  266.  
  267. INT  GetDisplay(void)
  268. {
  269.  
  270.    if (!digits)                        /* if nothing entered         */
  271.      operand = 0L;                     /* just use zero              */
  272.    else {
  273.      digits = 0;                       /* we've used this value      */
  274.      operand = atol(display);          /* convert the display value  */
  275.    }
  276.    return operand;                     /* return the value           */
  277. }
  278.  
  279. /*********************************************************************/
  280. /*                                                                   */
  281. /* SetDisplay(newdisplay) - Set the current display string to a new  */
  282. /*                display value.                                     */
  283. /*                                                                   */
  284. /*********************************************************************/
  285.  
  286. VOID SetDisplay(
  287.   LONG  newdisplay )                   /* new number to display      */
  288. {
  289.    sprintf(display,"%ld",newdisplay);  /* just use sprintf to update */
  290.  
  291. }
  292.  
  293. /*********************************************************************/
  294. /*                                                                   */
  295. /* ProcessArithmetic(newaction)  -  Process any pending arithmetic   */
  296. /*                operation updating the accumulator and the pending */
  297. /*                operation.                                         */
  298. /*                                                                   */
  299. /*********************************************************************/
  300.  
  301. VOID ProcessArithmetic(
  302.   LONG  newaction )                    /* new operator key pressed   */
  303. {
  304.  
  305.    switch(oldaction) {                 /* process prior action key   */
  306.  
  307.      case BUTTON_MULTIPLY:             /* multiplication             */
  308.  
  309.        accumulator *= GetDisplay();    /* multiplay accumulator by   */
  310.                                        /* current display            */
  311.        break;                          /* no more needed             */
  312.  
  313.      case BUTTON_DIVIDE:               /* division                   */
  314.  
  315.        accumulator /= GetDisplay();    /* divide accumulator by      */
  316.                                        /* current display            */
  317.        break;                          /* no more needed             */
  318.  
  319.      case BUTTON_PLUS:                 /* addition                   */
  320.  
  321.        accumulator += GetDisplay();    /* add accumulator to         */
  322.                                        /* current display            */
  323.        break;                          /* no more needed             */
  324.  
  325.      case BUTTON_MINUS:                /* subtraction                */
  326.  
  327.        accumulator -= GetDisplay();    /* subtract current display   */
  328.                                        /* from accumulator           */
  329.        break;                          /* no more needed             */
  330.  
  331.      case BUTTON_PROGRAM1:             /* function done as a REXX    */
  332.                                        /* program.  Just call the    */
  333.                                        /* external program.          */
  334.        ProcessProgram("PROGRAM1.RXC"); /* process the program        */
  335.        break;
  336.  
  337.      case BUTTON_PROGRAM2:             /* function done as a REXX    */
  338.                                        /* program.  Just call the    */
  339.                                        /* external program.          */
  340.        ProcessProgram("PROGRAM2.RXC"); /* process the program        */
  341.        break;
  342.  
  343.      case BUTTON_ENTER:                /* enter key                  */
  344.  
  345.        break;                          /* ignore old action          */
  346.  
  347.      default:
  348.        accumulator = GetDisplay();     /* just move display into the */
  349.                                        /* accumulator                */
  350.        break;                          /* no more needed             */
  351.  
  352.    }
  353.    oldaction = newaction;              /* remember the new action    */
  354. }
  355.  
  356. /*********************************************************************/
  357. /*                                                                   */
  358. /* ProcessProgram()  - Process a call to a programed Rexx function.  */
  359. /*                     The program is passed both the accumulator    */
  360. /*                     and the current display as strings.           */
  361. /*                                                                   */
  362. /*********************************************************************/
  363.  
  364. VOID ProcessProgram(
  365.   PSZ        macro_name )              /* macro to invoke            */
  366. {
  367.   RXSTRING   args[2];                  /* passed argument strings    */
  368.   RXSTRING   result;                   /* returned result string     */
  369.   UCHAR      accum[MAX_DIGITS+1];      /* buffer for converted accum */
  370.   INT        rc;                       /* Rexx return code           */
  371.   SHORT      return_code;              /* function return code       */
  372.  
  373.  
  374.   sprintf(accum, "%ld", accumulator);  /* format accumulator         */
  375.                                        /* build accumulator argument */
  376.   MAKERXSTRING(args[0], accum, strlen(accum));
  377.                                        /* and the current display    */
  378.   MAKERXSTRING(args[1], display, digits);
  379.                                        /* ask for result in display  */
  380.   MAKERXSTRING(result, display, DISPLAY_WIDTH);
  381.  
  382.   rc = RexxStart(2,                    /* two arguments              */
  383.                  args,                 /* array of arguments         */
  384.                  macro_name,           /* name of the macro          */
  385.                  NULL, NULL,
  386.                  RXFUNCTION,           /* calling this a function    */
  387.                  NULL,
  388.                  &return_code,         /* numeric value of return str*/
  389.                  &result);             /* returned string result     */
  390.   display[result.strlength] = '\0';    /* convert back to ASCII-Z    */
  391.   digits = result.strlength;           /* set new length             */
  392.  
  393.   accumulator = GetDisplay();          /* accumulator is new display */
  394.   return;                              /* finished (ignore errors    */
  395.                                        /* for now                    */
  396. }
  397.